//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
using System.Windows;
using System.Windows.Media;
using OpenLS.Spreadsheet.Internals;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal sealed class FontRecord : WorkbookLevelRecord
    {
        public FontRecord()
        {
            FontFamily = 2;
        }
        private IcvFont _colorIndex = IcvFont.Default;
        private ushort _fontWeight = 400;
        private byte _notUsed = 138;

        public FontRecord(Font font, BiffWriterWorkbookContext context)
        {
            Contract.Requires(font != null);
            Contract.Requires(context != null);
            string name;
            if (font.Name != null)
                name = font.Name;
            else if (font.FontFamily != null)
                name = font.FontFamily.Source;
            else if (context.Workbook.Theme.FontScheme != null)
            {
                name = context.Workbook.Theme.FontScheme.MinorFont.Latin.Source;
            }
            else
            {
                name = "Arial"; //\\hmm
            }
            _name = (ShortXLUnicodeString) name;
            IsBold = font.FontWeight == FontWeights.Bold;
            if (IsBold)
                _fontWeight = 700;
            IsItalic = font.FontStyle == FontStyles.Italic;
            HeightInPoints = font.Size;
            IsUnderlined = font.Underline != UnderlineType.None;
            UnderlineType = font.Underline;

            IndexedColor color = font.Foreground as IndexedColor;
            if (color != null)
                _colorIndex = (ushort) color.Index;//\\ maybe choose closest instead
        }

        public const int BlackColorIndex = 0x7FFF;

        private ShortXLUnicodeString _name;


        public byte CharSet { get; set; }

        public byte FontFamily { get; private set; }

        public UnderlineType UnderlineType { get; private set; }

        public VerticalRunAlignment VerticalRunAlignment { get; private set; }

        public double HeightInPoints { get; set; }

        public bool IsStruckOut { get; private set; }

        public bool IsUnderlined { get; set; }

        public bool IsItalic { get; set; }


        public bool IsBold { get; set; }
        [Flags]
        enum
            FontFlags: uint 
        {
            Bold=0x1,
            Italic = 0x2,
            Underlined = 0x4,
            StruckOut = 0x8,
        }

        internal override BiffRecordType RecordType
        {
            get { return BiffRecordType.Font; }
        }

        public string Name
        {
            get {
                return (string) _name;
            }
            set {
                _name = (ShortXLUnicodeString) value;
            }
        }

#if DEBUG
        private static int fontCount = 0;
#endif
        internal override void WriteContent(BiffWriterWorkbookContext context)
        {
            var writer = context.Writer;
            writer.Write((ushort)(HeightInPoints * 20));
            FontFlags flags = (FontFlags)0;
            if (IsBold)
                flags |= FontFlags.Bold;
            if (IsItalic)
                flags |= FontFlags.Italic;
            if (IsUnderlined)
                flags |= FontFlags.Underlined;
            if (IsStruckOut)
                flags |= FontFlags.StruckOut;
            writer.Write((ushort)flags);
            writer.Write((ushort)_colorIndex);
            writer.Write(_fontWeight);
            writer.Write((ushort)VerticalRunAlignment);
            writer.Write((byte)UnderlineType);
            writer.Write((byte)FontFamily);
            writer.Write((byte)CharSet);
            writer.Write(_notUsed);
            _name.Write(context, true);
        }

        protected override void ReadContent(BiffReaderContext context, int length)
        {
            long pos1 = context.BaseStream.Position;
            HeightInPoints = ((double) context.ReadUInt16())/20;
            var flags = (FontFlags)context.ReadUInt16();
            IsBold = (flags & FontFlags.Bold) != 0;
            IsItalic = (flags & FontFlags.Italic) != 0;
            IsUnderlined = (flags & FontFlags.Underlined) != 0;
            IsStruckOut = (flags & FontFlags.StruckOut) != 0;
            _colorIndex = context.ReadUInt16();
            _fontWeight = context.ReadUInt16();
            VerticalRunAlignment = (VerticalRunAlignment) context.ReadUInt16();
            UnderlineType = (UnderlineType) context.ReadByte();
            
            FontFamily = context.ReadByte();
            CharSet = context.ReadByte();
            _notUsed = context.ReadByte();
            _name.Read(context.Reader);
            #if DEBUG
            string s = (string)_name;
            Contract.Assert(s != null);
            long pos2 = context.BaseStream.Position;
            Contract.Assert(pos2 - pos1 == length);
            context.BaseStream.Position = pos1 + length;
            pos2 = context.BaseStream.Position;
            Contract.Assert(pos2 - pos1 == length);
#endif
        }

        private Font toFont(BiffReaderWorkbookContext context)
        {
            var result = new Font {};
#if DEBUG
            result.UnFreeze();
#endif
            result.Charset = CharSet;
            if (IsItalic)
                result.FontStyle = FontStyles.Italic;
            if (IsBold)
                result.FontWeight = FontWeights.Bold;
            if (IsStruckOut)
                result.Strike = true;
            if (IsUnderlined || this.UnderlineType != UnderlineType.None)
                result.Underline = this.UnderlineType;
            result.Name = (string) _name;
            if (result.Name !=  null)
                result.FontFamily = new FontFamily(result.Name);
            result.Size = HeightInPoints;
            if (_colorIndex != BlackColorIndex)
                result.Foreground = context.GetColor(_colorIndex); //\\StandardPalette.GetTextColor(_colorIndex));
#if DEBUG
            result.Freeze();
#endif
            return result;
        }

        public override void Apply(BiffReaderWorkbookContext ctx)
        {
            ctx.AddFont(toFont(ctx));
        }
    }
}